package com.hmall.gateway.routers;

import cn.hutool.json.JSONUtil;
import com.alibaba.cloud.nacos.NacosConfigManager;
import com.alibaba.nacos.api.config.listener.Listener;
import com.alibaba.nacos.api.exception.NacosException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionWriter;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;

import javax.annotation.PostConstruct;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Executor;

/**
 * @author xmy
 * @version 1.0
 */
@RequiredArgsConstructor
@Component
@Slf4j
public class DynamicRouterLoader {
    private final NacosConfigManager nacosConfigManager;
    private final RouteDefinitionWriter routeDefinitionWriter;
    private final Set<String> routeIds = new HashSet<>();
    private  final String dataId = "gateway-routes.json";
    private  final String group = "DEFAULT_GROUP";
    @PostConstruct
    public void initRouteerConfigListener() throws NacosException {
        log.info("配置监听器");

        //项目启动时，先拉去一次配置，并且配置监听器
         String configAndSignListener = nacosConfigManager.getConfigService()
                .getConfigAndSignListener(dataId, group, 5000, new Listener() {

                    @Override
                    public Executor getExecutor() {
                        return null;
                    }

                    @Override
                    public void receiveConfigInfo(String configAndSignListener) {

                        //监听到配置变更，更新路由表
                        updateConfigInfo(configAndSignListener);
                    }
                });
        updateConfigInfo(configAndSignListener);

    }

    private void updateConfigInfo(String configAndSignListener) {
        log.info("配置信息变更，更新路由表");
        log.info("监听到当前路由信息"+configAndSignListener);
        //解析配置文件
        List<RouteDefinition> routeDefinitions = JSONUtil.toList(configAndSignListener, RouteDefinition.class);
        //先删除所有旧的路由表
        for(String routeId : routeIds){
            routeDefinitionWriter.delete(Mono.just(routeId)).subscribe();
        }
        routeIds.clear();
        //更新路由表
        for(RouteDefinition routeDefinition : routeDefinitions){
            routeDefinitionWriter.save(Mono.just(routeDefinition)).subscribe();
            //纪录所有id
            routeIds.add(routeDefinition.getId());
        }

    }
}
